
#include <assert.h>
#include <sstream>
#include <stdint.h>
#include "logger.h"
#include <string.h>

using namespace std;
using namespace snda::comm::thread;

CLogger::CLogger()
: m_bInit(false)
{
}

CLogger::~CLogger()
{
}

int CLogger::Initialize(	const char* pszLogName)
{
	assert(pszLogName);

    m_oLogCtx.Initialize(pszLogName);	
    m_bInit = true;
	
    return 0;
}

void CLogger::Log(const char* sFormat, ...)
{
    assert(m_bInit);

	//CGuard m(m_oDebugLock);
	
	va_list ap;
	va_start(ap, sFormat);
    m_oLogCtx.Log(1, sFormat, ap);
	va_end(ap);

	return;
}

void CLogger::Log2Hex(const char* sLog, 
                         uint32_t nLen)
{
    assert(m_bInit && sLog);

	//CGuard m(m_oDebugLock);
	
	DebugHexDump(sLog, nLen);

    this->Log("%s\n%s", "[HEX-BEGIN]", m_achOBuf);
}

uint32_t CLogger::DebugHexDump_i(
                                   const char *pchInBuf,
                                   uint32_t nInBuf,
                                   char* pchOutBuf,
                                   uint32_t nOutBuf)
{
    const uint32_t BYTES_INPUT_PER_LINE = 16;
    const uint32_t BYTES_OUTPUT_PER_LINE = 68;
    
    unsigned char uchChar = '\0';
    char achTextVer[BYTES_INPUT_PER_LINE + 1];
    
    // Fit 16 bytes output in text mode per line, 4 chars per byte.
    uint32_t nMaxLen = (nOutBuf / BYTES_OUTPUT_PER_LINE) * BYTES_INPUT_PER_LINE;
    
    if (nInBuf > nMaxLen)
        nInBuf = nMaxLen;
    
    uint32_t i;
    
    uint32_t nLines = nInBuf / BYTES_INPUT_PER_LINE;
    for (i = 0; i < nLines; i++)
    {
        uint32_t j;
        
        for (j = 0 ; j < BYTES_INPUT_PER_LINE; j++)
        {
            uchChar = (unsigned char) pchInBuf[(i << 4) + j];
            sprintf (pchOutBuf, ("%02x "), uchChar);
            pchOutBuf += 3;
            if (j == 7)
            {
                sprintf (pchOutBuf, (" "));
                pchOutBuf++;
            }
            achTextVer[j] = isprint(uchChar) ? uchChar : '.';
        }
        
        achTextVer[j] = 0;
        
        sprintf (pchOutBuf, ("  %s\n"), achTextVer);
        
        while (*pchOutBuf != '\0')
            pchOutBuf++;
    }
    
    if (nInBuf % BYTES_INPUT_PER_LINE)
    {
        for (i = 0 ; i < nInBuf % BYTES_INPUT_PER_LINE; i++)
        {
            uchChar = (unsigned char) pchInBuf[nInBuf - nInBuf % BYTES_INPUT_PER_LINE + i];
            sprintf (pchOutBuf, ("%02x "), uchChar);
            pchOutBuf += 3;
            if (i == 7)
            {
                sprintf (pchOutBuf, (" "));
                pchOutBuf++;
            }
            achTextVer[i] = isprint (uchChar) ? uchChar : '.';
        }
        
        for (i = nInBuf % BYTES_INPUT_PER_LINE; i < BYTES_INPUT_PER_LINE; i++)
        {
            sprintf (pchOutBuf, ("   "));
            pchOutBuf += 3;
            if (i == 7)
            {
                sprintf (pchOutBuf, (" "));
                pchOutBuf++;
            }
            achTextVer[i] = ' ';
        }
        
        achTextVer[i] = 0;
        sprintf (pchOutBuf, ("  %s\n"), achTextVer);
    }
    
    return nInBuf;
}

void CLogger::DebugHexDump(
                               const char *pchInBuf, 
                               uint32_t nInBuf // Max Input buffer length = 4K
                               )
{
    DebugHexDump_i(pchInBuf, nInBuf, m_achOBuf, MAX_OUTPUT_HEX);    
}

